#include "AppleHIDConverter.h"
#include <math.h>
#include "LogUtils.h"

ulog_define( CarPlayHidApp, kLogLevelTrace, kLogFlags_Default, "CarPlayHidApp", NULL );
#define hid_ucat()					&log_category_from_name( CarPlayHidApp )
#define hid_ulog( LEVEL, ... )		ulog( hid_ucat(), (LEVEL), __VA_ARGS__ )
#define hid_dlog( LEVEL, ... )		dlogc( hid_ucat(), (LEVEL), __VA_ARGS__ )

static int							telephoneEventCycle = 0;

// 辅助函数：更新 reportDescriptor 字段
void updateReportField(HIDUsageDescriptor *field, uint8_t usagePage, uint8_t usage, uint8_t reportOffset, uint8_t reportSize) {
    if (field->enable == 0) {  // 仅在字段尚未启用时更新
        field->usagePage = usagePage;
        field->usage = usage;
        field->reportOffset = reportOffset;
        field->reportSize = reportSize;
        field->enable = 1;  // 标记为已启用
    }
}

// 主函数：解析 HID 描述符并计算报告大小
void parseHIDDescriptor(const uint8_t *desc, size_t descSize, HIDReportDescriptor *reportDescriptor) {
    size_t i = 0;  // 用于遍历描述符的索引
    uint8_t reportOffset = 0;  // 报告中字段的位偏移
    uint16_t totalBits = 0;    // 报告中所有字段的总位数

    uint8_t usagePage = 0;  // 当前使用页
    uint8_t usages[16] = { 0 };     // 用于存储多个使用的数组
    uint8_t usageCount = 0; // 找到的使用数量
    uint8_t reportSize = 0; // 每个字段的位大小

    while (i < descSize) {
        uint8_t prefix = desc[i++];  // 获取前缀字节
        switch (prefix) {
            case 0x05:  // Usage Page (使用页)
                usagePage = desc[i++];  // 获取使用页的值
                break;
            case 0x09:  // Usage (使用)
                usages[usageCount++] = desc[i++];  // 将使用存储到数组中
                break;
            case 0x75:  // Report Size (报告大小)
                reportSize = desc[i++];  // 获取报告大小（每个字段的位数）
                break;
            case 0x95: { // Report Count (报告计数)
                uint8_t reportCount = desc[i++];  // 获取报告计数（字段数量）
                uint16_t fieldBits = reportSize * reportCount;  // 计算此字段的总位数
                totalBits += fieldBits;  // 更新总位数

                // 为每个使用更新 reportDescriptor 字段
                if (usagePage == HID_USAGE_PAGE_TELEPHONY) {  // 检查是否为电话使用页
                    for (uint8_t j = 0; j < usageCount; j++) {  // 遍历所有找到的使用
                        switch (usages[j]) {
                            case HID_USAGE_HOOK_SWITCH:
                                updateReportField(&reportDescriptor->hookSwitch, usagePage, usages[j], reportOffset, reportSize);
                                hid_ulog(kLogLevelWarning, "HookSwitch: reportOffset = %d \n", reportDescriptor->hookSwitch.reportOffset);
                                break;
                            case HID_USAGE_FLASH:
                                updateReportField(&reportDescriptor->flash, usagePage, usages[j], reportOffset, reportSize);
                                hid_ulog(kLogLevelWarning, "Flash: reportOffset = %d \n", reportDescriptor->flash.reportOffset);
                                break;
                            case HID_USAGE_DROP:
                                updateReportField(&reportDescriptor->drop, usagePage, usages[j], reportOffset, reportSize);
                                hid_ulog(kLogLevelWarning, "Drop: reportOffset = %d \n", reportDescriptor->drop.reportOffset);
                                break;
                            // 如有更多使用需要处理，可以在此添加更多情况
                        }
                    }
                }

                reportOffset += fieldBits; // 更新位偏移以便下一个字段
                usageCount = 0; // 处理完一组使用后重置使用计数
                break;
            }
            case 0x81:  // Input (数据输入)
                // 处理数据输入（当前代码未实现具体逻辑）
                break;
            default:
                // 在此处理其他可能的 HID 描述符项
                break;
        }
    }

    // 计算报告的总字节长度，向上取整到最接近的字节数
    reportDescriptor->reportByteLength = (uint8_t)((totalBits + 7) / 8);  // 使用 (totalBits + 7) / 8 进行向上取整
}


// 函数：解析 HID 报告
void parseHIDReport(const HIDReportDescriptor *reportDescriptor, const uint8_t *report,void (*pFunc)(int keyCode)) {
	if( reportDescriptor->hookSwitch.enable == 1 )
	{
		uint8_t hookSwitchState = (report[reportDescriptor->hookSwitch.reportOffset / 8] >> (reportDescriptor->hookSwitch.reportOffset % 8)) & ((1 << reportDescriptor->hookSwitch.reportSize) - 1);
		hid_ulog( kLogLevelWarning,"Hook Switch: %s\n", hookSwitchState ? "Down" : "Up");
		if( pFunc != NULL && hookSwitchState == 1)
		{
			pFunc(100);
		}
	}

	if( reportDescriptor->flash.enable == 1 )
	{
		uint8_t flashState = (report[reportDescriptor->flash.reportOffset / 8] >> (reportDescriptor->flash.reportOffset % 8)) & ((1 << reportDescriptor->flash.reportSize) - 1);
		hid_ulog( kLogLevelWarning,"Flash: %s\n", flashState ? "Down" : "Up");
		if( pFunc != NULL && flashState == 1)
		{
			//接听键
			if( telephoneEventCycle == 0 ){
				telephoneEventCycle = 1;
				pFunc(100);
			} else {
				telephoneEventCycle = 0;
				pFunc(101);
			}

		}
	}

	if( reportDescriptor->drop.enable == 1 )
	{
		uint8_t dropState = (report[reportDescriptor->drop.reportOffset / 8] >> (reportDescriptor->drop.reportOffset % 8)) & ((1 << reportDescriptor->drop.reportSize) - 1);
		hid_ulog( kLogLevelWarning,"Drop: %s\n", dropState ? "Down" : "Up");
		if( pFunc != NULL && dropState == 1)
		{
			telephoneEventCycle = 0;
			pFunc(101);
		}
	}
}

int AppleHidTest() {
//    uint8_t hidDescriptor[] = {
//        0x05, 0x0B,        // Usage Page (Telephony)
//        0x09, 0x01,        // Usage (Phone)
//        0xA1, 0x01,        // Collection (Application)
//        0x05, 0x0B,        //   Usage Page (Telephony)
//        0x09, 0x20,        //   Usage (Hook Switch)
//        0x15, 0x00,        //   Logical Minimum (0)
//        0x25, 0x01,        //   Logical Maximum (1)
//        0x75, 0x01,        //   Report Size (1)
//        0x95, 0x01,        //   Report Count (1)
//        0x81, 0x02,        //   Input (Data,Var,Abs)
//        0x09, 0x21,        //   Usage (Flash)
//        0x15, 0x00,        //   Logical Minimum (0)
//        0x25, 0x01,        //   Logical Maximum (1)
//        0x75, 0x01,        //   Report Size (1)
//        0x95, 0x01,        //   Report Count (1)
//        0x81, 0x02,        //   Input (Data,Var,Abs)
//        0x09, 0x26,        //   Usage (Drop)
//        0x15, 0x00,        //   Logical Minimum (0)
//        0x25, 0x01,        //   Logical Maximum (1)
//        0x75, 0x01,        //   Report Size (1)
//        0x95, 0x01,        //   Report Count (1)
//        0x81, 0x02,        //   Input (Data,Var,Abs)
//        0x75, 0x01,        //   Report Size (1) for padding bits
//        0x95, 0x05,        //   Report Count (5) for padding bits
//        0x81, 0x01,        //   Input (Const,Array,Abs)
//        0xC0               // End Collection
//    };

	uint8_t hidDescriptor[] = {
	        0x05, 0x0B,        // Usage Page (Telephony)
	        0x09, 0x01,        // Usage (Phone)
	        0xA1, 0x01,        // Collection (Application)
	        0x05, 0x0B,        //   Usage Page (Telephony)
	        0x09, 0x21,        //   Usage (Flash)
	        0x15, 0x00,        //   Logical Minimum (0)
	        0x25, 0x01,        //   Logical Maximum (1)
	        0x75, 0x01,        //   Report Size (1)
	        0x95, 0x01,        //   Report Count (1)
	        0x81, 0x02,        //   Input (Data,Var,Abs)
	        0x75, 0x0F,        //   Report Size (15)
	        0x95, 0x01,        //   Report Count (1)
	        0x81, 0x01,        //   Input (Const,Array,Abs)
	        0xC0               // End Collection
	    };

    HIDReportDescriptor reportDescriptor = {0};
    parseHIDDescriptor(hidDescriptor, sizeof(hidDescriptor), &reportDescriptor);

    hid_ulog( kLogLevelWarning,"Total HID Report Size: %d bytes\n", reportDescriptor.reportByteLength);

    // 示例HID报告数据
//    uint8_t hidReport[] = { 0x01, 0x00 };  // 假设报告中 hook switch 为1，flash 为0，drop 为1
//    parseHIDReport(&reportDescriptor, hidReport);

    return 0;
}
